///////////////////////////////////////////////////////////
///////////////// Have an itch? Scratch it! ///////////////
///////////////////////// SCRATCH /////////////////////////
/////////////////////  A MUD  Server   ////////////////////
///////////////////// By: Jared Devall ////////////////////
/////////////////////      Thanks:     ////////////////////
/////////////////////  DIKU/Merc/ROM   ////////////////////
///////////////////// Aetas/Deus Gang  ////////////////////
/////////////////////       Beej       ////////////////////
///////////////////////////////////////////////////////////

#ifndef __SOCKET_H_
#define __SOCKET_H_

#include <list>
#include <string>

#ifndef WIN32
#include <sys/types.h>
#include <sys/time.h>
#else
#include <winsock.h>
#endif

#define MAX_BUFFER 4096

class Socket {
	bool         _disconnected;
	bool         _gotInput;
	std::string  _input;  // The data that the user is sending
	std::string  _output; // The data that the user will recieve	
	std::string  _ipAddress;   // The IP of user.
	std::string  _host;  // The Long host. __@__
	int		  _sockfd; // This is the socket number!
	
	public:
				 Socket();
				 ~Socket();
	void         FlushOutput( void );
	void         FlushInput( void );
	void         SetInput( const std::string & );
	void         SetOutput( const std::string & );
	void		 SetGotInput( bool value );
	bool		 GotInput( void );
	std::string  GetInput( void );
	std::string  GetOutput( void );
	void         SetSocketIP( const std::string & );
	std::string  GetSocketIP( void );
	void         SetSocketHost( const std::string & );
	std::string  GetSocketHost( void );
	int		  GetDescriptor( void );
	void         SetDescriptor( int desc );
	void         Send( char * message, ... );
	void         Send( const std::string & );
	void         SetDisconnected( bool value );
	bool         IsDisconnected( void );
};

class SocketServer {
	fd_set	   _fd_read; 
	fd_set	   _fd_exc;
	int	      _sockfd;	 
	int          _defaultPort;
	bool         _newConnection;
	
	enum RecieveReturn {
		Complete, Incomplete, Disconnected
    };

#if defined WIN32
    void InitWinsock( void ); // Need to Initialize Winsock.
    void DeInitWinsock( void ); // Call this when you close the Program.
#endif
	bool CreateSocket( void ); // Creates a Socket to listen with.
	bool ReuseAddress( void );
	bool BindSocket( int port );
	bool ListenSocket( void );	
	void ConceiveConnection( void );
	void ChaperoneConnections( void );	
	int  RecieveInput( Socket * socket );
	bool SendOutput( Socket * socket );
	void KillDisconnectedSockets( void );
	
	public:
	SocketServer();
	~SocketServer();
	static SocketServer &Instance();
	void KillSocket( Socket * socket );
	int  GetHostSocket( void );
	void SetHostSocket( int sockfd );
	void Start( void );
	void Start( int port );
	bool Monitor( );	
	std::list< Socket * > _socketList;	 // Connected sockets
};

// Our singleton instance
inline SocketServer &SocketServer::Instance() {
	static SocketServer instance;
	return instance;
}
#endif
